#!/bin/bash
# auto-register-runner.sh

# 检查是否为 root 用户
if [ "$(id -u)" != "0" ]; then
    echo "错误: 此脚本必须以 root 用户身份运行" >&2
    exit 1
fi

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case "$1" in
        --domain)
            DOMAIN_NAME="$2"
            shift 2
            ;;
        --k8s-token)
            K8S_TOKEN="$2"
            shift 2
            ;;
        --data-root)
            # 确保目录路径正确
            DATA_ROOT="${2%/}"  # 移除末尾的斜杠
            shift 2
            ;;
        *)
            echo "未知参数: $1"
            exit 1
            ;;
    esac
done

# 获取本机IP地址（优先使用内网地址）
get_local_ip() {
  # 尝试多种方法获取本机IP
  local ip
  ip=$(hostname -I 2>/dev/null | awk '{print $1}') || \
  ip=$(ip route get 1 | awk '{print $7; exit}' 2>/dev/null) || \
  ip=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n 1)

  echo "$ip"
}

if [ -z "$DOMAIN_NAME" ]; then
  # 尝试获取公网IP（带超时）
  PUBLIC_IP=$(curl -s --max-time 3 ifconfig.me 2>/dev/null || echo "")

  if [ -n "$PUBLIC_IP" ]; then
    DOMAIN_NAME=$PUBLIC_IP
  else
    # 获取本机IP地址
    LOCAL_IP=$(get_local_ip)
    if [ -n "$LOCAL_IP" ]; then
      DOMAIN_NAME=$LOCAL_IP
      echo "警告: 使用本机IP地址: $LOCAL_IP"
    else
      # 无法获取任何IP地址，退出安装
      echo "错误: 无法获取本机IP地址"
      echo "请手动设置 PRIVATE_REGISTRY 环境变量"
      echo "例如: export PRIVATE_REGISTRY='192.168.0.2'"
      exit 1
    fi
  fi
fi

# 设置数据目录（从环境变量获取或使用默认值）
DATA_ROOT=${DATA_ROOT:-$(dirname "$0")}

echo "==================================================="
echo "使用配置:"
echo "  域名: $DOMAIN_NAME"
echo "  数据目录: $DATA_ROOT"
echo "==================================================="

###########################################################
# Docker 环境安装与配置（仅在未安装时执行）
###########################################################

install_docker() {
    echo "开始安装 Docker 环境..."

    # 1. 更新系统
    echo "更新系统..."
    yum update -y

    # 2. 安装依赖包
    echo "安装依赖包..."
    yum install -y yum-utils device-mapper-persistent-data lvm2 vim telnet

    # 3. 设置 Docker 仓库
    echo "设置 Docker 仓库..."
    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo

    # 4. 安装 Docker
    echo "安装 Docker..."
    yum install -y docker-ce docker-ce-cli containerd.io

    # 5. 启动 Docker 并设置开机启动
    echo "启动 Docker 服务..."
    systemctl start docker
    systemctl enable docker

    # 6. 配置 Docker 镜像加速
    echo "配置 Docker 镜像加速..."
    mkdir -p /etc/docker
    # 创建配置文件
    cat > /etc/docker/daemon.json << EOF
{
    "registry-mirrors": [
        "https://docker.registry.cyou",
        "https://docker-cf.registry.cyou",
        "https://dockercf.jsdelivr.fyi",
        "https://docker.jsdelivr.fyi",
        "https://dockertest.jsdelivr.fyi",
        "https://mirror.aliyuncs.com",
        "https://dockerproxy.com",
        "https://mirror.baidubce.com",
        "https://docker.m.daocloud.io",
        "https://docker.nju.edu.cn",
        "https://docker.mirrors.sjtug.sjtu.edu.cn",
        "https://docker.mirrors.ustc.edu.cn",
        "https://mirror.iscas.ac.cn",
        "https://docker.rainbond.cc",
        "https://do.nark.eu.org",
        "https://dc.j8.work",
        "https://dockerproxy.com",
        "https://emo8i5zw.mirror.aliyuncs.com",
        "https://registry.docker-cn.com",
        "http://hub-mirror.c.163.com",
        "http://mirrors.ustc.edu.cn/",
        "https://mirrors.tuna.tsinghua.edu.cn/",
        "http://mirrors.sohu.com/"
    ],
    "insecure-registries": [
        "$DOMAIN_NAME:5000"
    ],
    "debug": true,
    "experimental": false
}
EOF

    # 7. 重启 Docker 使配置生效
    systemctl daemon-reload
    systemctl restart docker

    # 验证配置
    echo "Docker 配置验证:"
    docker info 2>&1 | grep -A 10 "Registry Mirrors" || echo "无法获取镜像仓库信息"
    docker info 2>&1 | grep -A 5 "Insecure Registries" || echo "无法获取不安全仓库信息"

    echo "Docker 配置完成"

    # 8. 验证 Docker 安装
    docker_version=$(docker --version 2>/dev/null)
    if [ -n "$docker_version" ]; then
        echo "Docker 安装成功: $docker_version"
    else
        echo "错误: Docker 安装失败" >&2
        exit 1
    fi
}

install_docker_compose() {
    echo "开始安装 Docker Compose 插件..."

    # 1. 确保已安装 Docker（因为这是依赖）
    if ! command -v docker &> /dev/null; then
        echo "错误: Docker 未安装，无法安装 Docker Compose 插件"
        exit 1
    fi

    # 2. 安装 Docker Compose 插件
    if command -v yum &> /dev/null; then
        echo "使用 yum 安装 Docker Compose 插件..."
        yum install -y docker-compose-plugin

        # 验证安装
        if docker compose version &> /dev/null; then
            echo "Docker Compose 插件安装成功"
        else
            echo "警告: 官方插件安装失败，请查看官方文档https://docs.docker.com/compose/install/linux/#install-using-the-repository"
        fi
    else
        echo "警告: yum 不可用，请查看官方文档https://docs.docker.com/compose/install/linux/#install-using-the-repository"
    fi
}

# 检查并安装 Docker（仅在未安装时执行）
if ! command -v docker &> /dev/null; then
    install_docker
else
    echo "Docker 已安装: $(docker --version)"
fi

# 获取宿主机 Docker 版本号（用于后续 Runner 注册）
DOCKER_VERSION=$(docker --version | awk '{print $3}' | tr -d ',' | cut -d'-' -f1)
if [ -z "$DOCKER_VERSION" ]; then
    # 如果获取失败，使用默认版本
    DOCKER_VERSION="26.1.4"
fi
echo "使用 Docker 版本: $DOCKER_VERSION"

# 检查并安装 Docker Compose
if ! command -v docker compose &> /dev/null; then
    install_docker_compose
else
    echo "Docker Compose 已安装: $(docker compose version)"
fi

if [ -f "all-images.tar" ]; then
    docker load -i all-images.tar
    docker images
fi

###########################################################
# 配置参数 - 支持环境变量覆盖
###########################################################

# 统一管理员密码
ADMIN_PASSWORD=${ADMIN_PASSWORD:-"Ad@123456789"}

# GitLab 管理员账号
GITLAB_ADMIN_USER=${GITLAB_ADMIN_USER:-"root"}

# SonarQube 管理员账号
SONAR_ADMIN_USER=${SONAR_ADMIN_USER:-"admin"}

# Runner 注册令牌
PRESET_TOKEN=${PRESET_TOKEN:-"sqa_4fb14d4be609dcd45a3cc1dcac5550e2652f908d"}

# 最大等待时间（秒）
MAX_WAIT_TIME=${MAX_WAIT_TIME:-600}

# 容器名称列表
CONTAINER_NAMES=("gitlab" "sonarqube" "gitlab-runner" "registry" "registry-ui")

# SonarQube Token 名称
SONAR_TOKEN_NAME=${SONAR_TOKEN_NAME:-"gitlab-integration-token"}

# 需要检查的端口列表
REQUIRED_PORTS=(80 443 2222 9000 5000 8080)

# GitLab 访问地址
GITLAB_URL="http://$DOMAIN_NAME"

echo "==================================================="
echo "使用配置:"
echo "  域名: $DOMAIN_NAME"
echo "  数据目录: $DATA_ROOT"
echo "  管理员密码: $ADMIN_PASSWORD"
echo "==================================================="

###########################################################
# 主脚本逻辑
###########################################################

# 0. 检查并安装 jq
if ! command -v jq &> /dev/null; then
    echo "安装 jq..."
    if [ -f /etc/redhat-release ]; then
        yum install -y jq
    elif [ -f /etc/lsb-release ]; then
        apt-get update
        apt-get install -y jq
    elif [ -f /etc/alpine-release ]; then
        apk add jq
    else
        echo "无法自动安装 jq，请手动安装后重新运行脚本"
        exit 1
    fi
fi

# 1. 目录创建与权限设置
echo "检查持久化数据目录..."
DIRS=(
  "${DATA_ROOT}/gitlab/config"
  "${DATA_ROOT}/gitlab/logs"
  "${DATA_ROOT}/gitlab/data"
  "${DATA_ROOT}/sonarqube/data"
  "${DATA_ROOT}/registry"
  "${DATA_ROOT}/gitlab-runner/config"
)

# 检查是否存在已有目录
EXISTING_DIRS=()
for dir in "${DIRS[@]}"; do
  if [ -d "$dir" ]; then
    EXISTING_DIRS+=("$dir")
  fi
done

# 如果有已存在目录，询问用户如何处理
if [ ${#EXISTING_DIRS[@]} -gt 0 ]; then
  echo "发现已存在的目录:"
  printf '  - %s\n' "${EXISTING_DIRS[@]}"

  while true; do
    read -p "是否删除这些目录并重新创建? [y/N]: " yn
    case $yn in
      [Yy]* )
        # 先停止并删除容器
        echo "停止相关容器..."
        # 使用 docker compose down 删除容器和网络
        docker compose -f ${DATA_ROOT}/docker-compose.yml down --volumes --remove-orphans
        # 清理残留网络
        docker network rm devops-net 2>/dev/null || true
        docker network prune -f

        # 等待容器完全停止
        sleep 5

        echo "正在删除旧目录..."
        sudo rm -rf "${EXISTING_DIRS[@]}"
        break
        ;;
      [Nn]* | "" )
        echo "保留现有目录继续执行..."
        break
        ;;
      * )
        echo "请输入 y 或 n"
        ;;
    esac
  done
fi

# 创建所需目录（如果不存在）
echo "创建所需的持久化数据目录..."
for dir in "${DIRS[@]}"; do
  if [ ! -d "$dir" ]; then
    echo "创建目录: $dir"
    sudo mkdir -p "$dir"
  fi
done

# 设置权限（生产环境应更严格）
echo "设置目录权限..."
sudo chmod -R 777 "${DATA_ROOT}"

# 2. 容器冲突检测与处理
echo "检查容器冲突..."
declare -a EXISTING_CONTAINERS=()
declare -a PORT_CONFLICTS=()

# 收集存在的容器（包括未运行的）
for container in "${CONTAINER_NAMES[@]}"; do
    if docker ps -a --format '{{.Names}}' | grep -q "^${container}\$"; then
        EXISTING_CONTAINERS+=("$container")

        # 检查容器是否在运行
        if docker ps -q -f "name=^${container}\$" | grep -q .; then
            echo "警告: 容器 $container 正在运行"
        fi
    fi
done

# 优化的端口冲突检测逻辑
declare -A CURRENT_PORTS=()
for container in "${EXISTING_CONTAINERS[@]}"; do
    docker container port "$container" 2>/dev/null | while read -r mapping; do
        port=$(echo "$mapping" | awk -F: '{print $2}')
        if [[ -n "$port" ]]; then
            CURRENT_PORTS["$port"]=1
        fi
    done
done

# 使用配置的端口列表
echo "检查端口: ${REQUIRED_PORTS[*]}"
for port in "${REQUIRED_PORTS[@]}"; do
    # 检查端口是否被其他容器占用（非当前项目）
    other_container_found=false
    while IFS= read -r other_container; do
        if docker container port "$other_container" 2>/dev/null | grep -q ":$port$"; then
            # 检查是否属于当前项目
            is_current_project=false
            for current_container in "${EXISTING_CONTAINERS[@]}"; do
                if [[ "$other_container" == "$current_container" ]]; then
                    is_current_project=true
                    break
                fi
            done

            if ! $is_current_project; then
                PORT_CONFLICTS+=("主机端口 $port 被容器 [$other_container] 占用")
                other_container_found=true
            fi
        fi
    done < <(docker ps --format '{{.Names}}' | grep -vE "^(${CONTAINER_NAMES[*]// /|})$")

    # 检查端口是否被系统进程占用（排除 Docker 相关进程）
    if ss -tuln | grep -q ":$port "; then
        # 获取占用端口的进程信息
        process_info=""
        while IFS= read -r line; do
            pid=$(echo "$line" | awk '{print $2}')
            cmd=$(ps -p "$pid" -o comm= 2>/dev/null)

            # 排除 Docker 相关进程
            if [[ ! "$cmd" =~ docker-proxy|dockerd|containerd ]]; then
                [[ -n "$process_info" ]] && process_info+=", "
                process_info+="$cmd($pid)"
            fi
        done < <(lsof -i :$port 2>/dev/null | awk 'NR>1 {print $1, $2}')

        [[ -n "$process_info" ]] && PORT_CONFLICTS+=("主机端口 $port 被系统进程占用 [$process_info]")
    fi

    # 如果端口被当前项目容器占用但未运行，报告冲突
    if [[ -n "${CURRENT_PORTS[$port]}" ]] && \
       ! docker ps --format '{{.Names}}' | grep -qE "^(${CONTAINER_NAMES[*]// /|})$"; then
        PORT_CONFLICTS+=("主机端口 $port 被当前项目容器占用（容器未运行）")
    fi
done

skip_deletion=false
if [ ${#EXISTING_CONTAINERS[@]} -gt 0 ] || [ ${#PORT_CONFLICTS[@]} -gt 0 ]; then
    if [ ${#EXISTING_CONTAINERS[@]} -gt 0 ]; then
        echo "发现已存在的容器:"
        for i in "${!EXISTING_CONTAINERS[@]}"; do
            printf "  [%d] %s\n" "$i" "${EXISTING_CONTAINERS[$i]}"
        done
    fi

    # 显示端口冲突信息
    if [ ${#PORT_CONFLICTS[@]} -gt 0 ]; then
        echo "检测到端口冲突:"
        printf "  - %s\n" "${PORT_CONFLICTS[@]}"
    fi

    while true; do
        echo "请选择操作:"
        [ ${#EXISTING_CONTAINERS[@]} -gt 0 ] && echo "  1) 删除所有容器"
        [ ${#EXISTING_CONTAINERS[@]} -gt 0 ] && echo "  2) 选择要删除的容器"
        [ ${#PORT_CONFLICTS[@]} -gt 0 ] && echo "  3) 尝试停止占用端口的进程"
        echo "  4) 跳过并继续（可能导致启动失败）"
        read -p "请输入选项编号 [4]: " choice

        choice=${choice:-4}

        case $choice in
            1)
                echo "正在删除所有容器..."
                # 使用 docker compose down 删除容器和网络
                docker compose -f ${DATA_ROOT}/docker-compose.yml down --volumes --remove-orphans
                # 清理残留网络
                docker network rm devops-net 2>/dev/null || true
                docker network prune -f
                break
                ;;
            2)
                read -p "请输入要删除的容器编号（多个用逗号分隔）: " indices

                # 转换为数组
                IFS=',' read -ra selected_indices <<< "$indices"

                declare -a containers_to_remove=()
                valid_selection=true

                for index in "${selected_indices[@]}"; do
                    # 验证是否为有效数字
                    if [[ "$index" =~ ^[0-9]+$ ]] && [ "$index" -lt "${#EXISTING_CONTAINERS[@]}" ]; then
                        containers_to_remove+=("${EXISTING_CONTAINERS[$index]}")
                    else
                        echo "错误: 无效的索引 '$index'"
                        valid_selection=false
                        break
                    fi
                done

                if $valid_selection; then
                    if [ ${#containers_to_remove[@]} -gt 0 ]; then
                        echo "正在删除选中的容器: ${containers_to_remove[*]}"
                        docker rm -f "${containers_to_remove[@]}"
                    fi
                    break
                fi
                ;;
            3)
                if [ ${#PORT_CONFLICTS[@]} -gt 0 ]; then
                    echo "尝试停止占用端口的进程..."
                    for port in "${REQUIRED_PORTS[@]}"; do
                        # 获取非Docker进程的PID
                        pids=$(lsof -i :$port | awk 'NR>1 {print $2}' | sort -u)
                        for pid in $pids; do
                            cmd=$(ps -p $pid -o comm=)
                            if [[ ! "$cmd" =~ docker-proxy|dockerd|containerd ]]; then
                                echo "停止占用端口 $port 的进程 (PID: $pid, 命令: $cmd)"
                                kill -9 $pid
                            fi
                        done
                    done
                fi
                break
                ;;
            4)
                echo "跳过冲突处理，继续执行..."
                skip_deletion=true
                break
                ;;
            *)
                echo "无效选项，请重新输入"
                ;;
        esac
    done
fi

# 3. 智能启动服务
echo "启动服务..."
export DOMAIN_NAME ADMIN_PASSWORD PRESET_TOKEN DATA_ROOT
if [ ${#EXISTING_CONTAINERS[@]} -gt 0 ] && ! $skip_deletion; then
    echo "检测到现有容器，执行更新操作..."
    # 停止并删除现有容器
    docker compose down
    # 清理网络
    docker network prune -f
    # 拉取最新镜像
    docker compose pull
    # 启动服务
    docker compose -f ${DATA_ROOT}/docker-compose.yml up -d
else
   # 检查是否所有容器都不存在
   ALL_CONTAINERS_MISSING=true
   for container in "${CONTAINER_NAMES[@]}"; do
       if docker ps -a -q -f "name=^${container}\$" | grep -q .; then
           ALL_CONTAINERS_MISSING=false
           break
       fi
   done

   # 如果所有容器都不存在，执行完整启动
   if $ALL_CONTAINERS_MISSING; then
       echo "未检测到任何容器，执行完整启动..."
       docker compose -f ${DATA_ROOT}/docker-compose.yml up -d
   else
       # 智能启动容器 - 只启动未运行的容器
       for container in "${CONTAINER_NAMES[@]}"; do
           if ! docker ps -q -f "name=^${container}\$" | grep -q .; then
               echo "启动容器: $container"
               docker compose -f ${DATA_ROOT}/docker-compose.yml up -d "$container"
           else
               echo "容器 $container 已在运行，跳过启动"
           fi
       done
   fi
fi

# 4. 增强的服务状态验证
echo "检查所有服务状态..."
ALL_RUNNING=true
for container in "${CONTAINER_NAMES[@]}"; do
    if docker ps -q -f "name=^${container}\$" | grep -q .; then
        echo "  ✓ $container 正在运行"
    else
        echo "  ✗ $container 未运行"
        ALL_RUNNING=false

        # 尝试启动未运行的容器
        echo "尝试启动 $container..."
        docker compose -f ${DATA_ROOT}/docker-compose.yml up -d "$container" >/dev/null 2>&1 || true

        # 等待并再次检查
        sleep 5
        if docker ps -q -f "name=^${container}\$" | grep -q .; then
            echo "  ✓ $container 已成功启动"
            ALL_RUNNING=true
        else
            echo "  ✗ $container 启动失败"
        fi
    fi
done

# 如果仍有服务未运行，尝试完全重建
if ! $ALL_RUNNING; then
    echo "部分服务启动失败，尝试完全重建环境..."
    docker compose -f ${DATA_ROOT}/docker-compose.yml down
    docker compose -f ${DATA_ROOT}/docker-compose.yml up -d
fi

# 5. GitLab健康检查
echo "等待GitLab完全启动..."
ELAPSED=0

while [[ $ELAPSED -lt $MAX_WAIT_TIME ]]; do
    # 检查容器状态和健康检查
    if docker inspect gitlab &> /dev/null; then
        HEALTH=$(docker inspect --format='{{.State.Health.Status}}' gitlab 2>/dev/null || echo "unknown")
        CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' gitlab 2>/dev/null || echo "unknown")
    else
        HEALTH=""
        CONTAINER_STATUS=""
    fi

    # 同时检查Web服务是否可访问
    HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${GITLAB_URL}/users/sign_in" 2>/dev/null || echo "000")

    if [[ "$HEALTH" == "healthy" && "$CONTAINER_STATUS" == "running" && "$HTTP_STATUS" =~ ^(200|302)$ ]]; then
        echo "GitLab已完全启动并可用"
        break
    fi

    echo "等待GitLab启动... (状态: ${HEALTH:-unknown}, HTTP: ${HTTP_STATUS}, 已等待 ${ELAPSED} 秒)"
    sleep 10
    ELAPSED=$((ELAPSED + 10))
done

if [[ $ELAPSED -ge $MAX_WAIT_TIME ]]; then
    echo "错误: GitLab在${MAX_WAIT_TIME}秒内未能完全启动"
    echo "最后状态:"
    docker inspect gitlab | jq '.[0].State' || true
    echo "容器日志:"
    docker logs gitlab --tail 50 || true
    exit 1
fi

# 6. 更新GitLab管理员密码
echo "更新GitLab管理员密码为统一密码..."
docker exec gitlab gitlab-rails runner "user = User.find_by_username('root'); user.password = '${ADMIN_PASSWORD}'; user.password_confirmation = '${ADMIN_PASSWORD}'; user.save!"

# 7. 增强的SonarQube启动等待
echo "等待SonarQube启动..."
ELAPSED=0
SONAR_READY=false

# 尝试启动SonarQube容器（确保运行）
docker compose -f ${DATA_ROOT}/docker-compose.yml up -d sonarqube

while [[ $ELAPSED -lt $MAX_WAIT_TIME && "$SONAR_READY" == false ]]; do
    # 检查容器是否运行
    if ! docker ps -q -f "name=sonarqube" | grep -q .; then
        echo "SonarQube容器未运行，尝试启动..."
        docker compose -f ${DATA_ROOT}/docker-compose.yml up -d sonarqube
        sleep 10
    fi

    # 尝试多种检测方式
    WEB_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:9000" 2>/dev/null || echo "000")
    API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:9000/api/system/status" 2>/dev/null || echo "000")

    # 检查API状态
    if [ "$API_STATUS" == "200" ]; then
        SONAR_STATUS=$(curl -s "http://localhost:9000/api/system/status" | jq -r '.status' 2>/dev/null || echo "unknown")
        if [ "$SONAR_STATUS" == "UP" ]; then
            SONAR_READY=true
            echo "SonarQube已完全启动并可用"
            break
        fi
    fi

    # 检查日志中的启动完成标记
    if docker logs sonarqube 2>&1 | grep -q "SonarQube is operational"; then
        SONAR_READY=true
        echo "通过容器日志检测到SonarQube已启动"
        break
    fi

    echo "等待SonarQube启动... (Web状态: ${WEB_STATUS}, API状态: ${API_STATUS}, 已等待 ${ELAPSED} 秒)"
    sleep 15
    ELAPSED=$((ELAPSED + 15))
done

if [ "$SONAR_READY" == false ]; then
    echo "警告: SonarQube在${MAX_WAIT_TIME}秒内未能完全启动，继续执行..."

    # 尝试获取容器日志以诊断问题
    echo "SonarQube容器日志(最后50行):"
    docker logs sonarqube --tail 50
fi

# 8. 增强的SonarQube配置（API方式）
echo "配置SonarQube与GitLab集成..."

# 8.1 使用API更新密码
echo "更新SonarQube管理员密码为统一密码..."
DEFAULT_SONAR_PASS="admin"
MAX_API_RETRY=10
SONAR_API_READY=false

# 等待SonarQube API就绪
echo "等待SonarQube API就绪..."
for ((attempt=1; attempt<=$MAX_API_RETRY; attempt++)); do
    if curl -s "http://localhost:9000/api/system/status" | grep -q "UP"; then
        SONAR_API_READY=true
        break
    fi
    echo "SonarQube API尚未就绪 ($attempt/$MAX_API_RETRY)，等待..."
    sleep 15
done

if ! $SONAR_API_READY; then
    echo "警告: SonarQube API在${MAX_API_RETRY}次尝试后仍不可用"
fi

# 尝试更新密码
PWD_UPDATED=false
for ((attempt=1; attempt<=5; attempt++)); do
    echo "尝试更新密码 (尝试 $attempt/5)..."
    UPDATE_PWD_RESPONSE=$(curl -s -X POST -u "${SONAR_ADMIN_USER}:${DEFAULT_SONAR_PASS}" \
        "http://localhost:9000/api/users/change_password" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        --data-urlencode "login=${SONAR_ADMIN_USER}" \
        --data-urlencode "previousPassword=${DEFAULT_SONAR_PASS}" \
        --data-urlencode "password=${ADMIN_PASSWORD}")

    # 检查更新是否成功
    if [ $? -eq 0 ]; then
        if echo "$UPDATE_PWD_RESPONSE" | grep -q "errors"; then
            echo "密码更新失败: $UPDATE_PWD_RESPONSE"
        else
            echo "密码更新成功"
            PWD_UPDATED=true
            break
        fi
    else
        echo "密码更新请求失败"
    fi

    sleep 10
done

if ! $PWD_UPDATED; then
    echo "警告: 无法更新SonarQube管理员密码"
    echo "请手动登录SonarQube更新密码"
fi

# 8.2 使用API生成SonarQube Token
echo "生成SonarQube Token..."
SONAR_TOKEN=""
MAX_TOKEN_RETRY=5

# 尝试获取现有Token
for ((attempt=1; attempt<=$MAX_TOKEN_RETRY; attempt++)); do
    EXISTING_TOKENS=$(curl -s -u "${SONAR_ADMIN_USER}:${ADMIN_PASSWORD}" \
        "http://localhost:9000/api/user_tokens/search" 2>/dev/null)

    SONAR_TOKEN=$(echo "$EXISTING_TOKENS" | jq -r ".userTokens[] | select(.name==\"${SONAR_TOKEN_NAME}\") | .token" 2>/dev/null)

    if [ -n "$SONAR_TOKEN" ] && [ "$SONAR_TOKEN" != "null" ]; then
        echo "找到现有Token: ${SONAR_TOKEN}"
        break
    fi
    sleep 5
done

# 如果没有现有Token则创建新Token
if [ -z "$SONAR_TOKEN" ] || [ "$SONAR_TOKEN" == "null" ]; then
    echo "创建新的SonarQube Token..."

    for ((attempt=1; attempt<=$MAX_TOKEN_RETRY; attempt++)); do
        echo "尝试创建Token (尝试 $attempt/$MAX_TOKEN_RETRY)..."
        SONAR_TOKEN_RESPONSE=$(curl -s -X POST -u "${SONAR_ADMIN_USER}:${ADMIN_PASSWORD}" \
            "http://localhost:9000/api/user_tokens/generate" \
            -H "Content-Type: application/x-www-form-urlencoded" \
            --data-urlencode "name=${SONAR_TOKEN_NAME}" 2>/dev/null)

        SONAR_TOKEN=$(echo "$SONAR_TOKEN_RESPONSE" | jq -r '.token' 2>/dev/null)

        if [ -n "$SONAR_TOKEN" ] && [ "$SONAR_TOKEN" != "null" ]; then
            echo "Token创建成功"
            break
        else
            echo "Token创建失败: $SONAR_TOKEN_RESPONSE"

            # 尝试使用默认密码作为备选方案
            SONAR_TOKEN_RESPONSE=$(curl -s -X POST -u "${SONAR_ADMIN_USER}:${DEFAULT_SONAR_PASS}" \
                "http://localhost:9000/api/user_tokens/generate" \
                -H "Content-Type: application/x-www-form-urlencoded" \
                --data-urlencode "name=${SONAR_TOKEN_NAME}" 2>/dev/null)

            SONAR_TOKEN=$(echo "$SONAR_TOKEN_RESPONSE" | jq -r '.token' 2>/dev/null)

            if [ -n "$SONAR_TOKEN" ] && [ "$SONAR_TOKEN" != "null" ]; then
                echo "使用默认密码创建Token成功"
                break
            fi

            sleep 15
        fi
    done
fi

# 如果仍然无法获取Token，使用OpenSSL生成随机值（仅用于显示）
if [ -z "$SONAR_TOKEN" ] || [ "$SONAR_TOKEN" == "null" ]; then
    echo "警告: 无法通过API创建SonarQube Token"
    echo "生成随机Token用于显示（实际无效）..."
    SONAR_TOKEN=$(openssl rand -hex 20)
    echo "请手动在SonarQube界面创建Token: ${SONAR_TOKEN_NAME}"
fi

# 9. 增强的GitLab API Token获取
echo "获取GitLab API Token..."
GITLAB_API_TOKEN=""

# 方法1: 使用SQL直接查询或创建Token
GITLAB_API_TOKEN=$(docker exec gitlab gitlab-rails runner \
  "begin
    token = PersonalAccessToken.find_by_name('sonarqube-integration')
    if token.nil?
      user = User.find_by_username('${GITLAB_ADMIN_USER}')
      token = user.personal_access_tokens.create!(
        name: 'sonarqube-integration',
        scopes: [:api],
        expires_at: 1.year.from_now
      )
    end
    puts token.token
  rescue => e
    puts 'ERROR: ' + e.message
  end" 2>/dev/null | grep -v 'ERROR:')

# 方法2: 使用API创建Token（如果SQL失败）
if [ -z "$GITLAB_API_TOKEN" ]; then
    echo "通过API创建GitLab API Token..."
    # 获取CSRF Token
    CSRF_TOKEN=$(curl -s -L "${GITLAB_URL}/users/sign_in" | grep csrf-token | sed 's/.*content="\([^"]*\)".*/\1/')
    # 登录获取会话Cookie
    SESSION_COOKIE=$(curl -s -c - "${GITLAB_URL}/users/sign_in" --data "user[login]=${GITLAB_ADMIN_USER}&user[password]=${ADMIN_PASSWORD}&authenticity_token=${CSRF_TOKEN}" | grep _gitlab_session | awk '{print $7}')

    # 创建Token
    CREATE_TOKEN_RESPONSE=$(curl -s -X POST -b "_gitlab_session=${SESSION_COOKIE}" -H "X-CSRF-Token: ${CSRF_TOKEN}" \
      "${GITLAB_URL}/api/v4/users/1/personal_access_tokens" \
      -H "Content-Type: application/json" \
      -d "{\"name\":\"sonarqube-integration\",\"scopes\":[\"api\"],\"expires_at\":\"$(date -d '+1 year' '+%Y-%m-%d')\"}")

    GITLAB_API_TOKEN=$(echo "$CREATE_TOKEN_RESPONSE" | jq -r '.token')
fi

# 10. 配置GitLab中的SonarQube服务
if [ -n "$GITLAB_API_TOKEN" ] && [ -n "$SONAR_TOKEN" ]; then
    echo "配置GitLab中的SonarQube服务..."

    # 创建SonarQube服务
    curl -s -X PUT -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
      "${GITLAB_URL}/api/v4/services/sonarqube" \
      -H "Content-Type: application/json" \
      -d "{
        \"active\": true,
        \"properties\": {
          \"sonarqube_url\": \"${GITLAB_URL}:9000\",
          \"automatic_vulnerabilities_creation\": true
        }
      }" >/dev/null 2>&1 || true
else
    echo "警告: 缺少必要的Token，跳过SonarQube服务配置"
fi

# 11. 创建全局配置组并设置变量
if [ -n "$GITLAB_API_TOKEN" ] && [ -n "$SONAR_TOKEN" ]; then
    echo "创建全局配置组并设置变量..."

    # 创建全局配置组
    GROUP_NAME="rey"
    GROUP_RESPONSE=$(curl -s -X POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
        "${GITLAB_URL}/api/v4/groups" \
        -H "Content-Type: application/json" \
        -d "{
            \"name\": \"${GROUP_NAME}\",
            \"path\": \"global-config\",
            \"visibility\": \"private\"
        }")

    # 检查组是否创建成功
    GROUP_ID=$(echo "$GROUP_RESPONSE" | jq -r '.id')
    if [ -z "$GROUP_ID" ] || [ "$GROUP_ID" == "null" ]; then
        echo "警告: 无法创建全局配置组，可能已存在"
        # 尝试获取现有组ID
        GROUP_RESPONSE=$(curl -s -X GET -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
            "${GITLAB_URL}/api/v4/groups?search=${GROUP_NAME}")
        GROUP_ID=$(echo "$GROUP_RESPONSE" | jq -r '.[0].id')
    fi

    if [ -n "$GROUP_ID" ] && [ "$GROUP_ID" != "null" ]; then
        echo "全局配置组ID: $GROUP_ID"

        # 设置组变量 SONAR_HOST_URL
        curl -s -X POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
            "${GITLAB_URL}/api/v4/groups/${GROUP_ID}/variables" \
            -H "Content-Type: application/json" \
            -d "{
                \"key\": \"SONAR_HOST_URL\",
                \"value\": \"${GITLAB_URL}:9000\",
                \"masked\": false,
                \"protected\": false
            }" >/dev/null 2>&1 || echo "设置组变量 SONAR_HOST_URL 失败"

        # 设置组变量 SONAR_TOKEN
        curl -s -X POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
            "${GITLAB_URL}/api/v4/groups/${GROUP_ID}/variables" \
            -H "Content-Type: application/json" \
            -d "{
                \"key\": \"SONAR_TOKEN\",
                \"value\": \"${SONAR_TOKEN}\",
                \"masked\": true,
                \"protected\": false
            }" >/dev/null 2>&1 || echo "设置组变量 SONAR_TOKEN 失败"

        echo "全局SonarQube组变量配置完成"
    else
        echo "警告: 无法获取全局配置组ID，跳过组变量配置"
    fi

    # 获取base64编码的kubeconfig
    KUBECONFIG_BASE64=$(cat /root/.kube/config | base64 -w0)

    # 设置组变量 KUBECONFIG_BASE64
    curl -s -X POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
        "${GITLAB_URL}/api/v4/groups/${GROUP_ID}/variables" \
        -H "Content-Type: application/json" \
        -d "{
            \"key\": \"KUBECONFIG_BASE64\",
            \"value\": \"${KUBECONFIG_BASE64}\",
            \"masked\": true,
            \"protected\": false
        }" || echo "设置组变量 KUBECONFIG_BASE64 失败"
else
    echo "警告: 缺少必要的Token，跳过组变量配置"
fi

# 12. 配置GitLab Kubernetes集成（使用k3s-offline-installer.sh传递的token）
if [ -n "$GITLAB_API_TOKEN" ] && [ -n "$K8S_TOKEN" ]; then
    echo "配置GitLab Kubernetes集成..."

    # 获取K3s集群信息
    K3S_API_SERVER="https://$DOMAIN_NAME:6443"

    # 添加集群到GitLab
    curl -s -X POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
      "${GITLAB_URL}/api/v4/admin/clusters" \
      -H "Content-Type: application/json" \
      -d "{
        \"name\": \"k3s-cluster\",
        \"enabled\": true,
        \"managed\": true,
        \"platform_kubernetes_attributes\": {
          \"api_url\": \"${K3S_API_SERVER}\",
          \"token\": \"${K8S_TOKEN}\",
          \"namespace\": \"\",
          \"authorization_type\": \"rbac\"
        }
      }" > /dev/null 2>&1 || echo "Kubernetes集群添加失败"

    echo "GitLab Kubernetes集成配置完成"
else
    echo "配置GITLAB_API_TOKEN $GITLAB_API_TOKEN"
    echo "配置K8S_TOKEN $K8S_TOKEN"
    echo "警告: 缺少必要的Token，跳过Kubernetes集成配置"
fi

# 13. 额外等待确保服务完全初始化
echo "等待服务完全初始化..."
sleep 30

# 14. 获取Runner注册令牌
if [ -n "$PRESET_TOKEN" ]; then
    REGISTRATION_TOKEN="$PRESET_TOKEN"
else
    echo "尝试获取注册令牌..."
    REGISTRATION_TOKEN=$(docker exec gitlab gitlab-rails runner \
        "puts Gitlab::CurrentSettings.current_application_settings.runners_registration_token" 2>/dev/null || true)

    # 如果获取失败，尝试备用方法
    if [ -z "$REGISTRATION_TOKEN" ]; then
        echo "使用备用方法获取令牌..."
        REGISTRATION_TOKEN=$(docker exec gitlab grep registration_token /etc/gitlab/gitlab.rb | awk '{print $2}' | tr -d '"' || true)
    fi
fi

# 验证令牌是否获取成功
if [ -z "$REGISTRATION_TOKEN" ]; then
    echo "错误: 无法获取注册令牌"
    exit 1
fi

# 15. 注册Runner
echo "正在注册Runner..."
REGISTER_OUTPUT=$(docker exec gitlab-runner gitlab-runner register \
  --non-interactive \
  --url "${GITLAB_URL}" \
  --registration-token "${REGISTRATION_TOKEN}" \
  --executor "docker" \
  --docker-image "docker:${DOCKER_VERSION}" \
  --description "Auto-Registered Runner" \
  --tag-list "android,ios,java" \
  --run-untagged \
  --locked=false \
  --docker-privileged=true \
  --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
  --docker-volumes "/certs/client" \
  --docker-volumes "/cache" \
  --docker-pull-policy="if-not-present" 2>&1)

echo "$REGISTER_OUTPUT"

# 检查注册结果
if ! echo "$REGISTER_OUTPUT" | grep -q "Runner registered successfully"; then
  echo "错误: Runner注册失败，尝试强制注册..."
  docker exec gitlab-runner gitlab-runner unregister --name "Auto-Registered Runner" 2>/dev/null || true
  docker exec gitlab-runner gitlab-runner register \
    --non-interactive \
    --url "${GITLAB_URL}" \
    --registration-token "${REGISTRATION_TOKEN}" \
    --executor "docker" \
    --docker-image "docker:${DOCKER_VERSION}" \
    --description "Auto-Registered Runner" \
    --tag-list "android,ios,java" \
    --run-untagged \
    --locked=false \
    --docker-privileged=true \
    --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
    --docker-volumes "/certs/client" \
    --docker-volumes "/cache" \
    --docker-pull-policy="if-not-present"
fi

# 16. 增强的Runner启动逻辑
echo "启动GitLab Runner服务..."
if docker exec gitlab-runner pgrep -f "gitlab-runner run" >/dev/null; then
    echo "Runner服务已在运行，发送HUP信号重载配置..."
    # 获取主进程PID
    RUNNER_PID=$(docker exec gitlab-runner pgrep -o -f "gitlab-runner run")
    # 发送重载配置信号
    docker exec gitlab-runner kill -HUP $RUNNER_PID
else
    echo "启动Runner服务..."
    docker exec -d gitlab-runner gitlab-runner run
fi

# 等待Runner启动
echo "等待Runner服务初始化..."
sleep 10

# 17. 验证Runner注册状态
echo "验证Runner注册状态..."
RUNNER_VALID=false

for attempt in {1..5}; do
  # 检查配置文件
  CONFIG_CONTENT=$(docker exec gitlab-runner cat /etc/gitlab-runner/config.toml 2>/dev/null)

  if echo "$CONFIG_CONTENT" | grep -q "token = \"glrt"; then
    RUNNER_VALID=true
    break
  fi

  echo "Runner配置验证尝试 ${attempt}/5 失败，等待重试..."
  sleep 10
done

if $RUNNER_VALID; then
  echo "Runner配置验证成功"
else
  echo "错误: Runner配置文件验证失败"
  echo "请手动检查 /etc/gitlab-runner/config.toml 文件内容"
  exit 1
fi

# 18. 验证Runner连接状态
echo "验证Runner连接状态..."
RUNNER_LIST=$(docker exec gitlab-runner gitlab-runner list 2>/dev/null || true)

if echo "$RUNNER_LIST" | grep -q "Auto-Registered Runner"; then
  echo "Runner已成功连接"
else
  echo "Runner尚未连接，但配置已存在"
  echo "GitLab可能需要几分钟时间同步Runner状态"
  echo "您也可以手动重启Runner容器:"
  echo "  docker compose restart gitlab-runner"
fi

# 19. 输出集成信息
echo ""
echo "==================================================="
echo "所有服务已成功部署并配置!"
echo ""
echo "GitLab 地址: ${GITLAB_URL}"
echo "Root 账号: ${GITLAB_ADMIN_USER}"
echo "Root 密码: ${ADMIN_PASSWORD}"
echo ""
echo "SonarQube 地址: ${DOMAIN_NAME}:9000"
echo "SonarQube 账号: ${SONAR_ADMIN_USER}"
echo "SonarQube 密码: ${ADMIN_PASSWORD}"
if [ -n "$SONAR_TOKEN" ]; then
    echo "SonarQube Token: ${SONAR_TOKEN}"
else
    echo "SonarQube Token: 未生成成功，请手动创建"
fi
echo ""
echo "Registry 地址: ${DOMAIN_NAME}:5000"
echo "Registry Web UI: http://${DOMAIN_NAME}:8080"
echo "  使用说明:"
echo "    1. 配置Docker客户端:"
echo "      在/etc/docker/daemon.json中添加:"
echo "        { \"insecure-registries\": [\"${DOMAIN_NAME}:5000\"] }"
echo "      然后执行: sudo systemctl restart docker"
echo "    2. 推送镜像示例:"
echo "      docker pull nginx:alpine"
echo "      docker tag nginx:alpine ${DOMAIN_NAME}:5000/nginx:alpine"
echo "      docker push ${DOMAIN_NAME}:5000/nginx:alpine"
echo ""
echo "Runner 令牌: ${REGISTRATION_TOKEN}"
echo ""
echo "Kubernetes 集成:"
echo "  - 集群名称: k3s-cluster"
echo "  - API 地址: https://${DOMAIN_NAME}:6443"
echo ""
echo "全局SonarQube配置:"
echo "  - 配置组: GlobalConfig"
echo "  - SONAR_HOST_URL: ${DOMAIN_NAME}:9000"
echo "  - SONAR_TOKEN: 已设置为组变量"
echo "==================================================="
echo ""
echo "SonarQube与GitLab集成状态: $([ -n "$SONAR_TOKEN" ] && echo "成功" || echo "部分失败")"
echo ""
if [ -n "$SONAR_TOKEN" ]; then
    echo "要在项目中使用SonarQube，请在.gitlab-ci.yml中添加:"
    echo "---------------------------------------------------"
    echo "variables:"
    echo "  SONAR_USER_HOME: \"\${CI_PROJECT_DIR}/.sonar\""
    echo "  GIT_DEPTH: \"0\""
    echo ""
    echo "sonarqube-check:"
    echo "  image: sonarsource/sonar-scanner-cli:latest"
    echo "  variables:"
    echo "    SONAR_USER_HOME: \"\${CI_PROJECT_DIR}/.sonar\""
    echo "  script:"
    echo "    - sonar-scanner"
    echo "      -Dsonar.projectKey=\${CI_PROJECT_NAME}"
    echo "      -Dsonar.projectName=\${CI_PROJECT_NAME}"
    echo "      -Dsonar.host.url=\${SONAR_HOST_URL}"
    echo "      -Dsonar.login=\${SONAR_TOKEN}"
    echo "      -Dsonar.projectVersion=\${CI_COMMIT_SHORT_SHA}"
    echo "      -Dsonar.sources=."
    echo "      -Dsonar.sourceEncoding=UTF-8"
    echo "  allow_failure: true"
    echo "---------------------------------------------------"
else
    echo "注意: 由于缺少SonarQube Token，请手动完成集成"
fi